package com.zhejiangzhengyuan.municipal_common.utils.excelFileUtils;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.extension.service.IService;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;

/**
 * @author lin_ju
 * @create on 2019/11/29
 */

// 有个很重要的点 DemoDataListener 不能被spring管理，要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class ExcelResolveListener<T> extends AnalysisEventListener<T> {
  /** 每隔500条存储数据库,然后清理list ，方便内存回收 */
  private static final int BATCH_COUNT = 500;

  private List<T> list = new ArrayList<>();
  /** 假设这个是一个DAO，当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。 */
  private IService<T> service;

  /**
   * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
   *
   * @param service service 处理类
   */
  public ExcelResolveListener(IService<T> service) {
    this.service = service;
  }

  /**
   * 这个每一条数据解析都会来调用
   *
   * @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
   */
  @Override
  public void invoke(T data, AnalysisContext context) {
    list.add(data);
    // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
    if (list.size() >= BATCH_COUNT) {
      saveData();
      // 存储完成清理 list
      list.clear();
    }
  }

  /** 所有数据解析完成了 都会来调用 doAfterAllAnalysed */
  @Override
  public void doAfterAllAnalysed(AnalysisContext context) {
    // 这里也要保存数据，确保最后遗留的数据也存储到数据库
    saveData();
    log.info("所有数据解析完成！");
  }

  /** 加上存储数据库 */
  private void saveData() {
    log.info("{}条数据，开始存储数据库！", list.size());
    service.saveBatch(list);
    log.info("存储数据库成功！");
  }
}
